package com.ruoyi.app.common

import cn.hutool.core.bean.BeanUtil
import cn.hutool.core.date.DateTime
import cn.hutool.core.date.DateUtil
import cn.hutool.core.io.FileUtil
import cn.hutool.core.util.RandomUtil
import cn.hutool.core.util.URLUtil
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.shaun.core.context.ProfileHolder
import com.ruoyi.app.domain.vo.AlipayResult
import com.ruoyi.back.enums.*
import com.ruoyi.common.constant.HttpStatus
import com.ruoyi.common.utils.file.FileUtils
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import ws.schild.jave.MultimediaInfo
import ws.schild.jave.MultimediaObject
import java.io.*
import java.math.BigDecimal
import java.math.RoundingMode
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLDecoder
import java.nio.channels.FileChannel
import java.util.*
import javax.servlet.http.HttpServletRequest

val qqInfoUrl: (String, String) -> String = { v1, v2 ->
    """
        https://graph.qq.com/user/get_user_info?access_token=$v1&oauth_consumer_key=102031338&openid=$v2
   """.trimIndent()
}

val empty = {
    Ok("暂无数据", null)
}

const val WEIXIN_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID"

val weixinInfoUrl: (String, String) -> String = { accessToken, openId ->
    WEIXIN_INFO_URL.replace("ACCESS_TOKEN", accessToken)
        .replace("OPENID", openId)
}

fun Date.format1(): String = if (DateUtil.year(this) > 2100) "永久" else DateUtil.format(this, "yyyy-MM-dd")

// 短信redis key 构建器
val messageRedisKey: (String) -> String = {"SHORT_MESSAGE::${it}"}

var ORDER_NUM = "${DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")}${RandomUtil.randomNumbers(8)}"

fun Double?.fen(): Int = this?.run { (this * 100).toInt() } ?: 0

fun String?.date(): Date? = this?.run { DateUtil.parse(this, "yyyy-MM-dd hh:mm:ss") }
fun Date.format(): String = if (DateUtil.year(this) > 2100) "永久" else DateUtil.format(this, "yyyy-MM-dd HH:mm:ss")

fun Date.year(): Int = DateUtil.year(this)
fun Date.month(): Int = DateUtil.month(this)
fun Date.day(): Int = DateUtil.dayOfMonth(this)

infix fun Date.add(n: Int): DateTime = DateUtil.offsetDay(this, n)

infix fun Date.lt(other: Date): Boolean = DateUtil.compare(this, other) < 0

infix fun Date.gt(other: Date): Boolean = DateUtil.compare(this, other) > 0

fun String.onlineKey(): String = "online:user:$this"


@ApiModel("分页实体")
data class PageMp<T>(
    @ApiModelProperty("实体列表")
    var records: List<T>? = null,

    @ApiModelProperty("总条数")
    var total: Long? = null,

    @ApiModelProperty("当前页大小")
    var size: Long? = null,

    @ApiModelProperty("当前页")
    var current: Long? = null,
)
fun <T> Page<T>.format(): PageMp<T> =
    PageMp<T>().apply {
        BeanUtil.copyProperties(this@format, this)
    }

fun String.aliPay(): AlipayResult {

    val params = mutableMapOf<String, String>()
    URLUtil.decode(this).split("&").map {
        it.split("=").run {
            params[get(0)] = get(1)
        }
    }
    return BeanUtil.mapToBean(params, AlipayResult::class.java, false, null)
}

fun HttpServletRequest.params(): Map<String, String> {

    val params = mutableMapOf<String, String>()
    if (parameterNames.hasMoreElements()) {
        params[parameterNames.nextElement()] = getParameter(parameterNames.nextElement())
    }
    return params
}

fun Int.loginType(): String =
    LoginTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.payType(): String =
    PayTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.userType(): String =
    UserTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.unitType(): String =
    UnitTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.urlType(): String =
    UrlTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.showPageType(): String =
    ShowPageTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.sendUserType(): SendUserTypeEnum? =
    SendUserTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0] }

fun Int.sendUserTypeStr(): String =
    SendUserTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.reportType(): String =
    ReportTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.noticeType(): String =
    NoticeTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.messageType(): String =
    MessageTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"

fun Int.templateType(): String =
    TemplateTypeEnum.values().filter { it.code == this }.takeIf { it.isNotEmpty() }
        ?.run { this[0].desc } ?: "未知"
fun Long.id(): String = "${this}:app"

fun String.parse(): Date = DateUtil.parse(this, "yyyy-MM-dd hh:mm:ss")


fun <T> Page<T>.pageInfo() =
    PageData<T>().apply {
        code = HttpStatus.SUCCESS
        msg = "查询成功"
        rows = this@pageInfo.records
        total = this@pageInfo.total
    }

fun String.inputStream(): InputStream? {
    val inputStream: InputStream?
    try {
        //url解码
        val url = URL(URLDecoder.decode(this, "UTF-8"));
        val conn = url.openConnection() as HttpURLConnection
        //设置超时间为3秒
        conn.connectTimeout = 3 * 1000;
        //防止屏蔽程序抓取而返回403错误
        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
        //得到输入流
        inputStream = conn.inputStream
    } catch (e: Exception) {
        throw e
    }

    return inputStream
}

fun String.videoTime(): String {
    var length = ""
    val file = File("classpath:")
    val inputStream = inputStream()
    try {
        val instance = MultimediaObject(FileUtil.writeFromStream(inputStream, file))
        val result: MultimediaInfo = instance.info
        val ls: Long = result.duration / 1000
        val hour = (ls / 3600).toInt()
        val minute = (ls % 3600).toInt() / 60
        val second = (ls - hour * 3600 - minute * 60).toInt()
        var hr = hour.toString()
        var mi = minute.toString()
        var se = second.toString()
        if (hr.length < 2) {
            hr = "0$hr"
        }
        if (mi.length < 2) {
            mi = "0$mi"
        }
        if (se.length < 2) {
            se = "0$se"
        }
        length = "$hr:$mi:$se"
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return length
}


fun String.videoSize(): String {

    var fc: FileChannel? = null
    var size = ""
    try {
        val fis = inputStream() as FileInputStream
        fc = fis.channel
        val fileSize = BigDecimal(fc.size())
        size = "${fileSize.divide(BigDecimal(1024 * 1024), 2, RoundingMode.HALF_UP)}MB"
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    } finally {
        if (null != fc) {
            try {
                fc.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
    return size;
}

fun id() = ProfileHolder.getProfile().id.toLong()
fun String.upAliTem() = Sign.addImageFaceTemplate(this.trans()) ?: throw Exception("上传阿里图片模板失败!")
